package com.wika.basics.widget

import android.animation.Animator
import android.animation.ValueAnimator
import android.content.Context
import android.graphics.Canvas
import android.graphics.Paint
import android.util.AttributeSet
import android.view.View
import androidx.core.content.ContextCompat
import com.wika.basics.R
import java.lang.ref.WeakReference

/**
 *@Description: 自定义圆点加载View
 *@Date: 2024/7/26 15:40
 *@Author: WangWeiShuo
 */
class LoadingView @JvmOverloads constructor(
    context: Context,
    attrs: AttributeSet? = null,
    defStyleAttr: Int = 0
): View(context, attrs, defStyleAttr) {

    private var hasAnimation = false
    private var paint: Paint? = null
    private var target: WeakReference<View>? = null
    private var animate: List<Animator>? = null

    private val SCALE = 1.0f

    private val ALPHA = 255

    private var scaleFloats = floatArrayOf(
        SCALE,
        SCALE,
        SCALE,
        SCALE,
        SCALE,
        SCALE,
        SCALE,
        SCALE
    )

    private var alphas = intArrayOf(
        ALPHA,
        ALPHA,
        ALPHA,
        ALPHA,
        ALPHA,
        ALPHA,
        ALPHA,
        ALPHA
    )

    init {
        initAttrs(context, attrs)
    }

    private fun initAttrs(context: Context, attrs: AttributeSet?) {
        val typedArray = context.obtainStyledAttributes(attrs, R.styleable.LoadingView)
        var normalColor = ContextCompat.getColor(context, R.color.blue_1E90FF)
        if(typedArray != null){
            // 背景
            normalColor = typedArray.getColor(R.styleable.LoadingView_normalColor,ContextCompat.getColor(context, R.color.blue_1E90FF))
            typedArray.recycle()
        }
        paint = Paint()
        paint?.color = normalColor
        paint?.style = Paint.Style.FILL
        paint?.isAntiAlias = true
        target = WeakReference(this)
    }

    override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec)
        setMeasuredDimension(measuredWidth, measuredHeight)
    }

    override fun onDraw(canvas: Canvas?) {
        super.onDraw(canvas)
        val radius = (width / 10).toFloat()
        for (i in 0..7) {
            canvas!!.save()
            val point: Point = circleAt(
                width,
                height, width / 2 - radius, i * (Math.PI / 4)
            )
            canvas.translate(point.x, point.y)
            canvas.scale(scaleFloats[i], scaleFloats[i])
            paint!!.alpha = alphas[i]
            canvas.drawCircle(0f, 0f, radius, paint!!)
            canvas.restore()
        }
    }

    /**
     * 圆O的圆心为(a,b),半径为R,点A与到X轴的为角α.
     * 则点A的坐标为(a+R*cosα,b+R*sinα)
     * @param width
     * @param height
     * @param radius
     * @param angle
     * @return
     */
    private fun circleAt(width: Int, height: Int, radius: Float, angle: Double): Point {
        val x = (width / 2 + radius * Math.cos(angle)).toFloat()
        val y = (height / 2 + radius * Math.sin(angle)).toFloat()
        return Point(x, y)
    }

    private fun createAnimation(): List<Animator>? {
        val animators: MutableList<Animator> = ArrayList()
        val delays = intArrayOf(0, 120, 240, 360, 480, 600, 720, 780, 840)
        for (i in 0..7) {
            val scaleAnim = ValueAnimator.ofFloat(1f, 0.4f, 1f)
            scaleAnim.duration = 1000
            scaleAnim.repeatCount = -1
            scaleAnim.startDelay = delays[i].toLong()
            scaleAnim.addUpdateListener { animation ->
                scaleFloats[i] = animation.animatedValue as Float
                postInvalidate()
            }
            scaleAnim.start()
            val alphaAnim = ValueAnimator.ofInt(255, 77, 255)
            alphaAnim.duration = 1000
            alphaAnim.repeatCount = -1
            alphaAnim.startDelay = delays[i].toLong()
            alphaAnim.addUpdateListener { animation ->
                alphas[i] = animation.animatedValue as Int
                postInvalidate()
            }
            alphaAnim.start()
            animators.add(scaleAnim)
            animators.add(alphaAnim)
        }
        return animators
    }

    class Point(var x: Float, var y: Float)

    private fun setAnimationStatus(animStatus: AnimStatus?) {
        if (animate == null) {
            return
        }
        val count: Int = animate?.size!!
        for (i in 0 until count) {
            val animator: Animator? = animate?.get(i)
            val isRunning = animator?.isRunning
            when (animStatus) {
                AnimStatus.START -> if (!isRunning!!) {
                    animator?.start()
                }

                AnimStatus.END -> if (isRunning!!) {
                    animator.end()
                }

                AnimStatus.CANCEL -> if (isRunning!!) {
                    animator.cancel()
                }

                else -> {}
            }
        }
    }


    enum class AnimStatus {
        START, END, CANCEL
    }

    override fun onLayout(changed: Boolean, left: Int, top: Int, right: Int, bottom: Int) {
        super.onLayout(changed, left, top, right, bottom)
        if (!hasAnimation) {
            hasAnimation = true
            animate = createAnimation()
        }
    }

    override fun setVisibility(v: Int) {
        if (visibility != v) {
            super.setVisibility(v)
            if (v == GONE || v == INVISIBLE) {
                setAnimationStatus(AnimStatus.END)
            } else {
                setAnimationStatus(AnimStatus.START)
            }
        }
    }

    override fun onAttachedToWindow() {
        super.onAttachedToWindow()
        if (hasAnimation) {
            setAnimationStatus(AnimStatus.START)
        }
    }

    override fun onDetachedFromWindow() {
        super.onDetachedFromWindow()
        setAnimationStatus(AnimStatus.CANCEL)
    }

}